package com.cta.service;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.LineIterator;
import org.apache.commons.io.filefilter.RegexFileFilter;
import org.apache.commons.lang.StringUtils;
import org.joda.time.LocalDate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.cta.entity.CallReport;
import com.cta.jms.TransferObject;
import com.cta.service.core.Processor;
import com.cta.service.report.MasterDataService;
import com.cta.view.json.RecoveryFile;
import com.cta.view.json.RecoveryFileData;
import com.cta.view.model.DurationLock;

@Service
public class RecoveryService {

	private static final Logger log = LoggerFactory.getLogger(RecoveryService.class);

	@Autowired
	private Processor recoveryCdr;

	@Autowired
	protected MasterDataService masterDataService;

	@Value("${folder.recovery}")
	private String recoveryFolder;

	public List<RecoveryFile> listAllFiles() {
		List<RecoveryFile> files = new ArrayList<RecoveryFile>();
		if (StringUtils.isNotEmpty(recoveryFolder)) {
			Collection<File> listFiles = FileUtils.listFiles(new File(recoveryFolder), new RegexFileFilter(
					"^.*log\\..*$"), null);
			for (File file : listFiles) {
				files.add(new RecoveryFile(file.getName()));
			}
		}

		return files;
	}

	public RecoveryFile readData(String fileName) throws IOException {
		RecoveryFile file = new RecoveryFile(fileName);
		if (StringUtils.isNotEmpty(fileName) && StringUtils.isNotEmpty(recoveryFolder)) {
			LineIterator iterator = FileUtils.lineIterator(new File(recoveryFolder + File.separatorChar + fileName));
			try {
				while (iterator.hasNext()) {
					file.addData(iterator.nextLine());
				}
			} finally {
				LineIterator.closeQuietly(iterator);
			}
		}
		return file;
	}

	@Transactional(readOnly = false)
	public boolean recovery(String fileName) throws Exception {
		boolean isOk = true;
		RecoveryFile data = readData(fileName);
		if (data.getDatas() != null && data.getDatas().size() > 0) {
			List<CallReport> allReport = new ArrayList<CallReport>(data.getDatas().size());
			for (RecoveryFileData d : data.getDatas()) {
				TransferObject msg = new TransferObject(d.getRowLog(), d.getPbxId());
				CallReport callReport = recoveryCdr.onMessage(msg);
				if (callReport != null) {
					allReport.add(callReport);
				} else {
					isOk = false;
					break;
				}
			}
			if (isOk && allReport.size() > 0) {
				// insert to database
				// save to database
				String tableName = null;
				DurationLock durationLock = null;
				for (CallReport callReport : allReport) {
					LocalDate localDate = callReport.getStartDate().toLocalDate();
					if (durationLock == null) {
						durationLock = masterDataService.createTable(localDate);
						tableName = durationLock.getTableName();
						log.info("Recovery: insert to databse");
						masterDataService.insertData(callReport.getInsertSql(tableName));
					}
				}
			}
		}
		if (isOk) {
			// rename file
			FileUtils.moveFile(new File(recoveryFolder + File.separatorChar + fileName), new File(recoveryFolder
					+ File.separatorChar + fileName + ".ok"));

		}
		return isOk;
	}

	public void delete(String fileName) throws IOException {
		File file = new File(recoveryFolder + File.separatorChar + fileName);
		file.delete();
	}
}
